package chpn.test.rowset.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.TreeMap;

import javax.sql.rowset.CachedRowSet;

import chpn.sql.rowset.Field;
import chpn.sql.rowset.ResultSetMeta;
 
 

public class ProxyCachedRowSetImpl implements SimpleRowSet  {
	LinkedList<Object[]> data = new LinkedList<Object[]>();
	ListIterator<Object[]> listIterator ;
	Object[] currentRow = null;
	TreeMap<String,Integer > fieldNameMap = new TreeMap<String,Integer >( String.CASE_INSENSITIVE_ORDER );
	private static final int FETCHCOUNT = 2000;  
	private int rowCount =0;
	private int pageSize = 0;
	private int columnCount =0;
	private ResultSetMetaData meta; 
	private ProxyCachedRowSetImpl(){}
	/**
	 * 创建一个 CachedRowSet 实例
	 * @return
	 */
	public static CachedRowSet newInstance() {
		ProxyCachedRowSetImpl rowset = new ProxyCachedRowSetImpl() ;
		InvocationHandler ih = new ProxyHandler( rowset );
		Class<?>[] interfaces = {CachedRowSet.class,SimpleRowSet.class};
		Object newProxyInstance = Proxy.newProxyInstance( ProxyCachedRowSetImpl.class.getClassLoader()  , interfaces, ih);
	
		return (CachedRowSet)newProxyInstance;
	}
	private void updateMeta(ResultSet rs) throws SQLException{
		ResultSetMetaData oldmeta = rs.getMetaData();
		ResultSetMeta meta = new ResultSetMeta(oldmeta);
		
		columnCount = oldmeta.getColumnCount();
		for(int i=1;i<=columnCount;i++){
			Field field = new Field();
			field.catalogName = oldmeta.getCatalogName( i );
			field.columnClassName = oldmeta.getColumnClassName( i );
			field.columnType = oldmeta.getColumnType( i );
			field.columnLabel = oldmeta.getColumnLabel( i );
			field.columnName = oldmeta.getColumnName( i );
			field.precision  = oldmeta.getPrecision( i );
			field.scale  = oldmeta.getScale( i );
			field.schemaName = oldmeta.getSchemaName( i );
			field.table = oldmeta.getTableName( i );
			meta.addField(field);
		}
		this.meta = meta;
		
	}
	public void populate(ResultSet rs, int start) throws SQLException { 
		if( start>-1){
			rs.absolute(start);
			rs.setFetchSize( this.pageSize );
		}else{

			rs.setFetchSize( FETCHCOUNT );
		}
		updateMeta(rs);
		rowCount = 0;
		while(rs.next()){
			Object[] row = new Object[ columnCount ];
			for(int i=1;i<=columnCount ;i++ ){
				row[ i-1 ] = rs.getObject( i );
			}
			data.add( row );
			rowCount++;
			if(start>-1 &&  rowCount> pageSize)
				break;
		} 
		//设置字段序号
		for(int i=1;i<=columnCount;i++){
			String fieldName = meta.getColumnLabel( i ); //使用 as 中的名称
			fieldNameMap.put( fieldName , i -1  ); //从0开始 
		}

	}

	public void populate(ResultSet rs ) throws SQLException {
		populate( rs , -1 ); 
		beforeFirst();
	} 
	@Override
	public boolean next() throws SQLException{
		if( listIterator.hasNext()){
			currentRow = listIterator.next();
			return true;
		}
		currentRow = null;
		return false;
	}
	@Override
	public void beforeFirst() throws SQLException{
		 listIterator = data.listIterator();
		 currentRow = null;
	}
	@Override
	public boolean first() throws SQLException{
		beforeFirst();
		return next();
	}
	@Override
	public String getString(String key ) throws SQLException{
		Object value = getObject( key );
		if( value==null)
			return null;
		return value.toString();
	}
	@Override
	public String getString(int index ) throws SQLException{
		Object value = getObject( index );
		if( value==null)
			return null;
		return value.toString();
	}
	@Override
	public Object getObject(String key ) throws SQLException{
		//int index = ; 
		return getObject( getIndex(key) );
	}
	@Override
	public Object getObject(int index ) throws SQLException{
		if( index==-1)
			return null;
		if( index<1 || index> columnCount ){
			throw new SQLException("必须是1-"+columnCount + "之间的数字" );
		} 
		return currentRow[ index -1  ]; 
	}
 
	

	@Override
	public int getInt(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).intValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).intValue();
		}
		String svalue = value.toString();
		try{
			return Integer.parseInt( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为int类型");
		}
		
	}

	@Override
	public int getInt(String key) throws SQLException {
		int index = getIndex(key); 
		return getInt( index );
		
	}

	@Override
	public long getLong(int index ) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).longValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).longValue();
		}
		String svalue = value.toString();
		try{
			return Long.parseLong( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为long类型");
		}
		
	}

	@Override
	public long getLong(String key) throws SQLException {
		int index = getIndex( key ); 
		return getLong( index );
		
	}
	
	

	@Override
	public float getFloat(String key) throws SQLException {
		int index = getIndex( key ); 
		return getFloat( index );
	}

	@Override
	public float getFloat(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).floatValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).floatValue();
		}
		String svalue = value.toString();
		try{
			return Float.parseFloat( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为float类型");
		}
		
	}

	@Override
	public BigDecimal getBigDecimal(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return null ;
		return ((BigDecimal)value) ;
		
	}

	@Override
	public BigDecimal getBigDecimal(String key) throws SQLException {
		int index = getIndex( key ); 
		return getBigDecimal( index );
		
	}

	@Override
	public double getDouble(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).doubleValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).doubleValue();
		}
		String svalue = value.toString();
		try{
			return Double.parseDouble( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为double类型");
		}
		
	}

	@Override
	public double getDouble(String key) throws SQLException {
		int index = getIndex( key ); 
		return getDouble( index );
		
	}
//	@Override
//	public Date getDate(String key) throws SQLException {
//		int index = getIndex( key ); 
//		return getDate( index );
//		
//	}
	private int getIndex(String key){
		Integer index = fieldNameMap.get(key); 
		if( index==null)
			return  -1;
		return index +1;
	}
//	@Override
//	public Date getDate(int index) throws SQLException {
//
//		Object value = getObject(index );
//		if(value==null)
//			return null ;
//		if( value instanceof Date ){
//			return ((Date)value);
//		}
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Date getDate(int index, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Date getDate(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(int index) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(String fieldName) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(int index, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}

	@Override
	public Timestamp getTimestamp(int index) throws SQLException {

		Object value = getObject(index );
		int type = meta.getColumnType( index );
		if( type== Types.TIMESTAMP ){
			return ((Timestamp)value);
		} 
		throw new SQLException("无法转换类型主Timestamp:" + value );
		
	}

	@Override
	public Timestamp getTimestamp(String fieldName) throws SQLException {
		return getTimestamp( getIndex( fieldName ));
		
	}

//	@Override
//	public Timestamp getTimestamp(int index, Calendar calendar) throws SQLException {
//
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Timestamp getTimestamp(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//	@Override
//	public Blob getBlob(String fieldName) throws SQLException {
//		throw new NotImplementedException();
//		
//	}

	@Override
	public boolean getBoolean(int index) throws SQLException {
		Object val = getObject(index);
		return new Integer(1).equals(val);
		
	}

	@Override
	public boolean getBoolean(String key) throws SQLException {
		Object val = getObject( key );
		return new Integer(1).equals(val);
		
	}

	@Override
	public byte getByte(int index) throws SQLException {
		Object val = getObject( index );
		if( val==null)
			return 0;
		return (Byte)val;
		
	}

	@Override
	public byte getByte(String key) throws SQLException {
		Object val = getObject( key );
		if( val==null)
			return 0;
		return (Byte)val;
		
	}

//	@Override
//	public byte[] getBytes(int index) throws SQLException {
//		Object val = getObject( index );
//		if( val==null)
//			return null;
//		return (byte[])val;
//		
//	}
//
//	@Override
//	public byte[] getBytes(String fieldName) throws SQLException {
//		return getBytes( getIndex(fieldName));
//		
//	}
	
	public void setPageSize( int pageSize ) throws SQLException{
		this.pageSize = pageSize;
	}
 

	@Override
	public ResultSetMetaData getMetaData() throws SQLException {
		return meta;
		
	}
	@Override
	public void setObject(int colIndex, Object value) throws SQLException  {
		if( colIndex<1){
			throw new SQLException("应从1开始");
		}
		Object[] row = getCurrentRow();
		if( colIndex>row.length){
			row =Arrays.copyOf( row ,  colIndex );
			data.add(  row );
		}
		row[ colIndex -1 ] = value;
	} 
	private Object[] getCurrentRow() { 
		return currentRow;
	}
	@Override
	public void setObject(String field, Object value) throws SQLException  {
		int index = getIndex( field );
		if( index==-1){
			addColumn( field );
			index = getIndex( field );
		} 
		setObject( index , value );
		
	}
	private void addColumn(String field) {
		fieldNameMap.put( field , fieldNameMap.size() );
		columnCount = fieldNameMap.size();
		
	}
	


}
